﻿//===============================================================================
//	MapServer.cpp
//	地图服务器
//===============================================================================
#ifdef _MSC_VER
#ifdef USE_VLD_CHECK_LEAK
#include "vld.h"
#endif
#endif

#include <unordered_map>
#include "MapServer.h"

#include "../../3rd/libjson/json.h"

#include "ManagerHelper.h"
#include "../share/MessageDef.h"
#include "../share/GameHostManager.h"
#include "../share/proxyclient_service.h"
#include "../share/client_msg.h"
#include "../share/server_msg.h"
//#include "MapSlot.h"
#include "map_logic.h"
#include "map_playermgr.h"
#include "mapobj_manager.h"
#include "SceneConfigureTable.h"
#include "scene_manager.h"

#ifdef _MSC_VER
char * g_dump_exe_name = "MapServer";
#endif
//---------------------------------------------------------------------------------------------------------------
// 连接管理
//---------------------------------------------------------------------------------------------------------------

bool SocketGateGame::Exist(uint32_t area_id)
{
	std::unordered_map<uint32_t, uint32_t>::iterator it = gate_fd_game.find(area_id);

	if (it != gate_fd_game.end()) {
		return true;
	}
	return false;
}

uint32_t SocketGateGame::GetCurrentFd(uint32_t area_id)
{
	auto it = gate_fd_game.find(area_id);
	if (it == gate_fd_game.end()) {
		return -1;
	}
	return it->second;
}

void SocketGateGame::Set(uint32_t area_id, uint32_t fd)
{
	if (Exist(area_id)) {
		gate_fd_game[area_id] = fd;
	}
	else {
		gate_fd_game.insert(std::make_pair(area_id, fd));
	}

}
//---------------------------------------------------------------------------------------------------------------
// map server
//---------------------------------------------------------------------------------------------------------------

MapServer::MapServer()
{
	client_gate_fd = 0;
}

MapServer::~MapServer()
{

}

int32_t MapServer::Initialize()
{
	CMAPObjManager::GetInstance().Initialize();
	manager_helper::InitializeAllManager(8, 1);

//	MapSlot::GetInstance().Init();

	//manager_helper::DispatchSceneToMapSlot();

	uint16_t _listen_port = GameHostManager::GetInstance().GetMapHostListenPort();
	if (0 == _listen_port)
	{
		LOG_ERROR("default","ERROR >> Read map server listen port fail");
		return -1;
	}
	map_net_.Initialize(1024 * 100, 1024 * 100);
	int32_t rtn = map_net_.Startup(_listen_port);
	if (rtn != ::common::SUCCEED)
	{
		return rtn;
	}


	CProxyClientService& proxy_client = CProxyClientService::GetInstance();
	proxy_client.InitializeServer(GetServiceType(), GetServiceID(), this);
	proxy_client.Initialize(1024 * 100, 1024 * 100);

	CMapLogic::GetInstance().Initialize();
	CMapPlayerManger::GetInstance().Initialize();
	SceneConfigureTable::GetInstance();
	CSceneManager::GetInstance().Initialize();
	return 0;
}

int32_t MapServer::Finalize()
{
	CMAPObjManager::GetInstance().Finalize();
	manager_helper::DestoryAllManager();
//	MapSlot::ReleaseInstance();
	CMapLogic::ReleaseInstance();
	CMapPlayerManger::ReleaseInstance();
	return 0;
}

int32_t MapServer::client_msg_dispatch(std::string& msg, unsigned long uid, uint32_t msgId)
{
	Json::Value m_jv;
	m_jv["msg"] = msg;
	m_jv["_gate_fd"] = (int32_t)uid;
	//m_jv["_area_id"] = 
	std::string send_str = JsonWriter(m_jv);

	// 不存在的连接去掉 去掉不合理的玩家
	/*
	if (!server_net.is_connnected(uid)) {
		LOG_ERROR("default", "send msg to client not found connected uid[%d]", uid);
		Player * player = CMapPlayerManger::GetInstance().GetPlayerBySocket(uid);
		if (player == nullptr) {
			return 0;
		}
		CJsonMessageBase bmsg;
		bmsg.ParseAcceptJson(msg);
		CMapLogic::SLoginPlayerQuitGameNotify(*player, bmsg);
		return 0;
	}
	*/
	Player * player = CMapPlayerManger::GetInstance().GetPlayerBySocket(uid);
	if (player == nullptr) {
		LOG_ERROR("default", "map - gate msg error player is null or cant find socket fd");
		return 0;
	}
	// 获取gate 连接到 map 的mapchannel
	uint32_t gate_map_fd = SocketGateGame::GetInstance().GetCurrentFd(player->GetArea());
	CMapChannel* channel = map_net_.GetChannel(gate_map_fd);
	if (channel == NULL)
	{
		LOG_ERROR("default", "channel is null!");
		map_net_.CloseChannel(gate_map_fd);
		return -1;
	}
	const char* msg_body = send_str.c_str();
	::common::CNetMsgTransfer::out_tcp_for_client(*channel, gate_map_fd, msgId, msg_body, msg.size());
	return ::common::SUCCEED;
	//return server_net.client_msg_dispatch(send_str, SocketGateGame::GetInstance().GetCurrentFd(player->GetArea()), msgId);
}

int32_t MapServer::AddClientMsg(uint32_t socketId, uint32_t msgId, std::string &msg)
{
	CJsonMessageBase bmsg;
	bool ret = bmsg.ParseAcceptJson(msg);
	const Json::Value tmp_jv = bmsg.GetJsonValue();

	int32_t gate_fd = tmp_jv["_gate_fd"].asInt();
	int32_t msg_id = tmp_jv["msgid"].asInt();
	uint32_t area_id = tmp_jv["_area_id"].asUInt();

	// 注册gate
	if (msg_id == register_gate_to_map)
	{
		client_gate_fd = socketId;
		SocketGateGame::GetInstance().Set(area_id, socketId);
		return 0;
	}


	CClientSocketMsg client_msg;
	client_msg.SetMsg(msg, gate_fd, msg_id);
	AddClientMsgPtr(client_msg);
	return 0;
}

void MapServer::ProcessClientMsg(CClientSocketMsg& val)
{
	LOG_DEBUG("default"," process socket msg %d processed Begin =====", val.m_protocol_number);

	CJsonMessageBase msg;
	bool ret = msg.ParseAcceptJson(val.msg_);
	if (ret == false)
	{
		LOG_ERROR("default","msg parse err!  msgid[%d][%s]", val.m_protocol_number, val.msg_.c_str());
		return;
	}
	msg.set_from_socket_id(val.fd_);

	Player* player = CMapPlayerManger::GetInstance().GetPlayerBySocket(val.fd_);
	if (val.m_protocol_number == map_player_login_req && player == NULL)
	{
		CMapLogic::GetInstance().PlayerLoginMapServerRequest(val.fd_, msg);
		player = CMapPlayerManger::GetInstance().GetPlayerBySocket(val.fd_);
		return;
	}

	
	if (player == NULL)
	{
		LOG_INFO("default","player is not online when process msg[%d]", val.m_protocol_number);
		if (val.m_protocol_number == player_map_ping_req) {
			return;
		}

		if (val.m_protocol_number == player_walk)
		{
			const Json::Value& m_jv = msg.GetJsonValue();
			int32_t gate_fd = m_jv["_gate_fd"].asInt();
			int32_t area_id = m_jv["_area_id"].asInt();

			LOG_INFO("default",">> step_return: pplayer is null.");
			// 重启服务过来的步行消息，让客户端重新注册下
			Json::Value jm;
			jm["msgid"] = map_player_login_again_notify;
			jm["_gate_fd"] = gate_fd;
			jm["_area_id"] = area_id;
			
			std::string str = JsonWriter(jm);

			//MapServer::GetInstance().client_msg_dispatch(str, val.fd_, map_player_login_again_notify);
			send_2_game(map_player_login_again_notify, str, area_id);
		}
		return;
	}

	MapPlayerMsgProcess process = GetPlayerMsgFactory().GetMsgProcess(val.m_protocol_number);
	if (process == NULL)
	{
		LOG_ERROR("default","process is null! msgid[%u]", val.m_protocol_number);
		return;
	}

	process(*player, msg);

	LOG_DEBUG("default"," process socket msg %d processed OK =====", val.m_protocol_number);
}

void MapServer::TickUpdate()
{
//	MapSlot::GetInstance().TickUpdate();
	CMapPlayerManger::GetInstance().TickUpdate();
	CSceneManager::GetInstance().TickUpdate();
	CProxyClientService::GetInstance().EnableReconnect(true);
}

int32_t MapServer::ServerStart()
{
	CProxyClientService::GetInstance().CheckConnect();
	return 0;
}

void MapServer::client_close_socket(uint32_t uid)
{
	LOG_INFO("default", " close client uid:%u", uid);
	//server_net.close_client(uid);
	map_net_.CloseChannel(uid);
}

void MapServer::del_client_socket(uint32_t fd)
{
	CMapPlayerManger::GetInstance().OnPlayerDisconnect(fd);
}

int main(int argc, char* argv[])
{
#ifdef _MSC_VER
	SetCtrlCHandle(true);
#endif
	int retcode = MapServer::GetInstance().ServiceMain(argc, argv);
	MapServer::ReleaseInstance();
#ifdef _MSC_VER
	SetCtrlCHandle(false);
#endif
	return retcode;
}



void CMapChannel::OnMsgEvent()
{
	while (true)
	{

		uint32_t msg_id = 0;

		std::string content;

		bool ret_trans = ::common::CNetMsgTransfer::in_tcp_for_client(*this, content, msg_id);

		if (ret_trans == false) {
			return;
		}
		CJsonMessageBase bmsg;
		bool ret = bmsg.ParseAcceptJson(content);
		const Json::Value tmp_jv = bmsg.GetJsonValue();

		int32_t gate_fd = tmp_jv["_gate_fd"].asInt();
		//int32_t msg_id = tmp_jv["msgid"].asInt();
		uint32_t area_id = tmp_jv["_area_id"].asUInt();

		// 注册gate
		if (msg_id == register_gate_to_map)
		{
			MapServer::GetInstance().SetMapGateFd(fd());
			SocketGateGame::GetInstance().Set(area_id, fd());
			return ;
		}


		CClientSocketMsg client_msg;
		client_msg.SetMsg(content, gate_fd, msg_id);
		MapServer::GetInstance().ProcessClientMsg(client_msg);

	}
}

void CMapChannel::OnConnect()
{
	LOG_ERROR("default", "on connect");
}

void CMapChannel::OnDisconnect()
{
	LOG_ERROR("default", "on disconnect");
	MapServer::GetInstance().del_client_socket(fd());
}
